package org.dromara.answerFront.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.answer.Final.UserExamsStatusFinal;
import org.dromara.answer.domain.AiExams;
import org.dromara.answer.domain.AiUserExams;
import org.dromara.answer.domain.bo.AiExamsBo;
import org.dromara.answer.domain.bo.AiQuestionsBo;
import org.dromara.answer.domain.bo.AiUserAnswersBo;
import org.dromara.answer.domain.bo.AiUserExamsBo;
import org.dromara.answer.domain.vo.AiExamsVo;
import org.dromara.answer.domain.vo.AiQuestionsVo;
import org.dromara.answer.domain.vo.AiUserAnswersVo;
import org.dromara.answer.domain.vo.AiUserExamsVo;
import org.dromara.answer.mapper.AiUserExamsMapper;
import org.dromara.answer.service.*;
import org.dromara.answerFront.service.IFrontUserExamsService;
import org.dromara.answerFront.vo.ComputationResultVo;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.dromara.answer.domain.AiExamQuestions;
import org.dromara.answer.domain.AiUserAnswers;

/**
 * 用户考试记录Service业务层处理
 *
 * @author Lion Li
 * @date 2025-04-09
 */
@RequiredArgsConstructor
@Service
public class FrontUserExamsServiceImpl implements IFrontUserExamsService {

    private final IAiUserExamsService userExamsService;
    private final IAiUserAnswersService userAnswersService;
    private final IAiQuestionsService questionsService;
    private final IAiOptionsService optionsService;
    private final IAiExamsService examsService;
    private final IAiExamQuestionsService examQuestionsService;

    private static AiUserAnswersBo apply(AiUserAnswers n) {
        AiUserAnswersBo userAnswers = new AiUserAnswersBo();
        BeanUtils.copyProperties(n, userAnswers);
        return userAnswers;
    }


    @Override
    public List<AiUserExamsVo> queryList(AiUserExamsBo bo) {
        bo.setUserId(LoginHelper.getUserId());
        List<AiUserExamsVo> aiUserExamsVo = userExamsService.queryList(bo);
        return aiUserExamsVo;
    }

    @Override
    public AiUserExamsVo queryById(Long userExamId) {

        AiUserExamsVo aiUserExamsVo = userExamsService.queryById(userExamId);

        aiUserExamsVo.setQuestions(examsService.qeuryQuestionsByExamId(aiUserExamsVo.getExamId()));

        aiUserExamsVo.getQuestions().forEach(item -> {
            item.setOptions(optionsService.queryListByQuestionId(item.getQuestionId()));
            item.setUserAnswer(userAnswersService
                    .queryByQuestionIdAndUserExamId(userExamId, item.getQuestionId()));
        });

        return aiUserExamsVo;
    }

    @Override
    public AiUserExamsBo start(AiUserExamsBo bo) {

        AiExams byId = examsService.getById(bo.getExamId());

        if (ObjectUtils.isEmpty(byId)){
            throw new ServiceException("试卷不存在");
        }

        bo.setStartTime(new Date());
        bo.setUserId(LoginHelper.getUserId());

        bo.setTotalScore(byId.getTotalScore());
        bo.setTotalQuestions(byId.getQuestionCount());
        bo.setPassScore(byId.getPassScore());
        bo.setDuration(byId.getDuration());

        userExamsService.insertByBo(bo);
        return bo;
    }

    @Override
    public AiUserExamsVo submit(AiUserExamsBo bo) {
        // 1. 数据验证
        if (bo.getUserExamId() == null) {
            throw new ServiceException("考试记录ID不能为空");
        }
        
        // 验证考试记录是否存在且属于当前用户
        AiUserExamsVo existingExam = userExamsService.queryById(bo.getUserExamId());
        if (existingExam == null) {
            throw new ServiceException("考试记录不存在");
        }
        
        if (!existingExam.getUserId().equals(LoginHelper.getUserId())) {
            throw new ServiceException("无权操作此考试记录");
        }
        
        // 检查考试状态，防止重复提交
        if (UserExamsStatusFinal.COMPLETED.equals(existingExam.getStatus()) || 
            UserExamsStatusFinal.GRADED.equals(existingExam.getStatus())) {
            throw new ServiceException("考试已提交，不能重复提交");
        }
        
        // 2. 设置提交时间和状态
        bo.setSubmitTime(new Date());
        bo.setUserId(LoginHelper.getUserId());
        bo.setStatus(UserExamsStatusFinal.COMPLETED);
        
        // 3. 批量获取题目信息和试卷绑定题目信息
        List<AiQuestionsVo> questions = examsService.qeuryQuestionsByExamId(existingExam.getExamId());
        if (questions == null || questions.isEmpty()) {
            throw new ServiceException("试卷题目不存在");
        }
        
        // 构建题目ID到题目信息的映射
        Map<Long, AiQuestionsVo> questionMap = questions.stream()
                .collect(java.util.stream.Collectors.toMap(AiQuestionsVo::getQuestionId, q -> q));
        
        // 4. 保存用户答案列表并进行评分，同时计算总分和正确题目数
        int totalScore = 0;
        int correctCount = 0;

        List<AiUserAnswersBo> collect = userAnswersService.
                lambdaQuery()
                .eq(AiUserAnswers::getUserExamId, bo.getUserExamId())
                .list().stream()
                .map(n -> apply(n))
                .collect(Collectors.toList());

        bo.setUserAnswersList(collect);

        if (bo.getUserAnswersList() != null && !bo.getUserAnswersList().isEmpty()) {
            for (AiUserAnswersBo answerBo : bo.getUserAnswersList()) {

                // 评分并保存答案，同时获取得分和正确性
                ScoreResult scoreResult = gradeAndSaveAnswer(answerBo, questionMap);

                // 累加总分和正确题目数
                totalScore += scoreResult.getScoreEarned();
                if (scoreResult.isCorrect()) {
                    correctCount++;
                }
            }
        }

        // 5. 更新考试记录的分数和正确题目数
        bo.setScore(totalScore);
        bo.setCorrectCount(correctCount);
        
        // 6. 计算总用时
        if (bo.getStartTime() != null && bo.getSubmitTime() != null) {
            long diffInMillies = bo.getSubmitTime().getTime() - bo.getStartTime().getTime();
            bo.setTotalTime((int) (diffInMillies / (1000)));
        }
        
        // 7. 计算单题最长答题时间（maxTime字段存储单题最长停留时间，单位：秒）
        int maxStayTime = 0;
        if (bo.getUserAnswersList() != null && !bo.getUserAnswersList().isEmpty()) {
            for (AiUserAnswersBo answerBo : bo.getUserAnswersList()) {
                if (answerBo.getStayTime() != null && answerBo.getStayTime() > maxStayTime) {
                    maxStayTime = answerBo.getStayTime();
                }
            }
        }
        
        bo.setMaxTime(maxStayTime);
        
        // 8. 判断考试是否通过（基于得分和及格分数）
        if (existingExam.getPassScore() != null && totalScore >= existingExam.getPassScore()) {
            // 考试通过，可以在这里添加额外的逻辑，比如记录通过状态
            // 注意：当前数据库表中没有专门的"是否通过"字段，可以通过比较score和passScore来判断
        }
        
        // 9. 计算考试完成率（答题数/总题数）
//        int answeredQuestions = bo.getUserAnswersList() != null ? bo.getUserAnswersList().size() : 0;
//        int totalQuestions = existingExam.getTotalQuestions() != null ? existingExam.getTotalQuestions() : questions.size();

        // 10. 计算正确率（答对题数/总题数）
        // double accuracyRate = totalQuestions > 0 ? (double) correctCount / totalQuestions * 100 : 0;
        
        // 11. 更新考试记录
        userExamsService.updateByBo(bo);
        
        // 12. 返回更新后的考试记录
        AiUserExamsVo result = userExamsService.queryById(bo.getUserExamId());
        
        // 可以在这里添加日志记录考试完成情况
        // System.out.println("考试提交完成 - 用户ID: " + bo.getUserId() + 
        //                   ", 考试ID: " + existingExam.getExamId() + 
        //                   ", 得分: " + totalScore + "/" + existingExam.getTotalScore() + 
        //                   ", 正确题数: " + correctCount + "/" + totalQuestions + 
        //                   ", 正确率: " + String.format("%.2f", accuracyRate) + "%" +
        //                   ", 用时: " + bo.getTotalTime() + "分钟" +
        //                   ", 是否通过: " + (existingExam.getPassScore() != null && totalScore >= existingExam.getPassScore() ? "是" : "否"));
        
        return result;
    }
    
    /**
     * 评分并保存答案（优化版本）
     * @param answerBo 用户答案
     * @param questionMap 题目信息映射
     * @return 评分结果
     */
    private ScoreResult gradeAndSaveAnswer(AiUserAnswersBo answerBo, Map<Long, AiQuestionsVo> questionMap) {
        // 从缓存中获取题目信息
        AiQuestionsVo question = questionMap.get(answerBo.getQuestionId());
        if (question == null) {
            throw new ServiceException("题目不存在");
        }
        
        // 从AiExamQuestions对象中获取该题在本次考试中的分值
        Integer questionScore = question.getQuestionScore();
        if (questionScore == null) {
            throw new ServiceException("题目在考试中的分值配置不存在");
        }
        
        // 设置题目类型
        answerBo.setQuestionType(question.getQuestionType());
        
        // 根据题目类型进行评分
        boolean isCorrect = false;
        int scoreEarned = 0;
        
        switch (question.getQuestionType()) {
            case "single_choice":
                isCorrect = gradeSingleChoice(answerBo.getAnswerContent(), question.getAnswer());
                scoreEarned = isCorrect ? questionScore : 0;
                break;
            case "multiple_choice":
                isCorrect = gradeMultipleChoice(answerBo.getAnswerContent(), question.getAnswer());
                scoreEarned = isCorrect ? questionScore : 0;
                break;
            case "fill_blank":
                // 填空题不进行自动评分，需要人工评分
                isCorrect = false; // 默认不正确，需要人工评分
                scoreEarned = 0; // 默认0分，需要人工评分
                break;
            case "true_false":
                isCorrect = gradeTrueFalse(answerBo.getAnswerContent(), question.getAnswer());
                scoreEarned = isCorrect ? questionScore : 0;
                break;
            default:
                throw new ServiceException("不支持的题目类型: " + question.getQuestionType());
        }
        
        // 设置评分结果
        answerBo.setIsCorrect(isCorrect ? 1 : 0);
        answerBo.setScoreEarned(scoreEarned);
        
        // 保存或更新答案
        if (answerBo.getRecordId() == null || answerBo.getRecordId() == 0) {
            userAnswersService.insertByBo(answerBo);
        } else {
            userAnswersService.updateByBo(answerBo);
        }
        
        // 返回评分结果
        return new ScoreResult(isCorrect, scoreEarned);
    }
    
    /**
     * 评分单选题
     */
    private boolean gradeSingleChoice(String userAnswer, String correctAnswer) {
        if (StringUtils.isEmpty(userAnswer) || StringUtils.isEmpty(correctAnswer)) {
            return false;
        }
        return userAnswer.trim().equals(correctAnswer.trim());
    }
    
    /**
     * 评分多选题
     */
    private boolean gradeMultipleChoice(String userAnswer, String correctAnswer) {
        if (StringUtils.isEmpty(userAnswer) || StringUtils.isEmpty(correctAnswer)) {
            return false;
        }
        // 多选题答案通常是JSON格式的数组，需要解析比较
        try {
            // 这里可以根据实际存储格式进行解析
            // 假设答案格式为 "A,B,C" 或 JSON 数组
            return userAnswer.trim().equals(correctAnswer.trim());
        } catch (Exception e) {
            return false;
        }
    }
    
    /**
     * 评分判断题
     */
    private boolean gradeTrueFalse(String userAnswer, String correctAnswer) {
        if (StringUtils.isEmpty(userAnswer) || StringUtils.isEmpty(correctAnswer)) {
            return false;
        }
        // 判断题答案可能是 "true"/"false" 或 "1"/"0"
        String normalizedUserAnswer = userAnswer.trim().toLowerCase();
        String normalizedCorrectAnswer = correctAnswer.trim().toLowerCase();
        
        return normalizedUserAnswer.equals(normalizedCorrectAnswer);
    }


    @Override
    public AiUserAnswersBo selectAnswer(AiUserAnswersBo bo) {
        bo.setUserId(LoginHelper.getUserId());
        if (bo.getRecordId() == null || bo.getRecordId() == 0) {
            userAnswersService.insertByBo(bo);
        }else {
            userAnswersService.updateByBo(bo);
        }
        return bo;
    }

    @Override
    public TableDataInfo<AiExamsVo> queryListPaper(AiExamsBo bo, PageQuery pageQuery) {
        bo.setStatus(1);
        return examsService.queryPageList(bo, pageQuery);
    }

    @Override
    public AiExamsVo queryPaperById(Long examId) {
        AiExamsVo aiExamsVo = examsService.queryById(examId);

        if (aiExamsVo == null){
            throw new RuntimeException("试卷不存在");
        }

        aiExamsVo.setQuestions(examsService.qeuryQuestionsByExamId(examId));

        for (AiQuestionsVo question : aiExamsVo.getQuestions()) {
            question.setOptions(optionsService.queryListByQuestionId(question.getQuestionId()));
        }

        return aiExamsVo;
    }

    /**
     * 评分结果内部类
     */
    private static class ScoreResult {
        private final boolean correct;
        private final int scoreEarned;
        
        public ScoreResult(boolean correct, int scoreEarned) {
            this.correct = correct;
            this.scoreEarned = scoreEarned;
        }
        
        public boolean isCorrect() {
            return correct;
        }
        
        public int getScoreEarned() {
            return scoreEarned;
        }
    }
}
